/* sht21.c

Copyright (C) Alex S. (mailto: md5sum@alexsp.ru)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details
http://www.gnu.org/licenses/gpl-2.0.html.

You should have received a copy of the GNU General Public License
along with this program in the file gpl-2.0.txt;
if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "sht21.h"

#if HUMIDITY==21

#define sht21_addr 0x80
#define sht21_rh_nohold 0xf5
#define sht21_rh_hold 0xe5
#define sht21_t_nohold 0xf3
#define sht21_t_hold 0xe3
#define ifTWI(a) if (TWI_check(a)) {TWI_stop();TWCR=0;return ERROR;}
#define crc8(a,b) _crc_ibutton_update(a,b);

static uint8_t sht21_crc(uint8_t *data){
	uint8_t crc=0;
	uint8_t j;
	crc ^= *(data+1);
	for (j=8;j>0;--j) {
		if (crc & 0x80) crc = (uint16_t)(crc <<1) ^ (uint16_t)0x131;
		else crc= (crc << 1);
	}
	crc ^= *(data);
	for (j=8;j>0;--j) {
		if (crc & 0x80) crc = (uint16_t)(crc <<1) ^ (uint16_t)0x131;
		else crc= (crc << 1);
	}
	return crc;
}

hw_ret_status get_sht21_nohold(uint8_t * rh, int8_t * t){
	uint16_t read_value;
	uint8_t checksum,crc;

	TWI_start();
	ifTWI(TW_START);
	TWI_send_data_nack(sht21_addr|TW_WRITE);
	ifTWI(TW_MT_SLA_ACK);
	TWI_send_data_nack(sht21_rh_nohold);
	ifTWI(TW_MT_DATA_ACK);
	_delay_ms(50);
	TWI_restart();
	ifTWI(TW_REP_START);
	TWI_send_data_nack(sht21_addr|TW_READ);
	ifTWI(TW_MR_SLA_ACK);
	TWI_send_data_ack(0xFF);
	read_value=TWDR<<8;
	TWI_send_data_ack(0xFF);
	read_value|=TWDR;
	TWI_send_data_nack(0xFF);
	checksum=TWDR;
	TWI_stop();
	if (sht21_crc((uint8_t *)&read_value)!=checksum) return CRC;
	read_value&=0xfffc;
	*rh=((double)read_value/65536L)*125-5.5;


	TWI_start();
	ifTWI(TW_START);
	TWI_send_data_nack(sht21_addr|TW_WRITE);
	ifTWI(TW_MT_SLA_ACK);
	TWI_send_data_nack(sht21_t_nohold);
	ifTWI(TW_MT_DATA_ACK);
	_delay_ms(150);
	TWI_start();
	ifTWI(TW_START);
	TWI_send_data_nack(sht21_addr|TW_READ);
	ifTWI(TW_MR_SLA_ACK);
	TWI_send_data_ack(0xFF);
	read_value=TWDR<<8;
	crc=0;
	crc^=TWDR;
	TWI_send_data_ack(0xFF);
	read_value|=TWDR&0xfc;
	crc^=TWDR;
	TWI_send_data_nack(0xFF);
	checksum=TWDR;
	TWI_stop();
	if (sht21_crc((uint8_t *)&read_value)!=checksum) return CRC;
	read_value&=0xfffc;
	*t=((double)read_value/65536L)*175.72-46.85;

	return SUCCESS;
}

#endif /* HUMIDITY */
